// 接口

// TypeScript的核心原则之一是对值所具有的结构类型检查
// 它优势被称作 "鸭式辨型法" 或 "结构性子类型化"
 
// 在TypeScript里,
// 接口的作用就是为这些类型命名和为你的代码
// 或第三方代码定义契约

// 常规接口实现
function printLabel(
    labelleObj:{
        size:string,label:string,value:string
    }){
    console.log(labelleObj.label,labelleObj.value)
}
let myObj = {
    size:"10",
    label:"size 10 object",
    value:"ldq"
};
printLabel(myObj);
// 上述代码功能如下:
// 1.创造了一个函数,
// 该函数默认传入的参数应该是一个对象, 
// 该对象内部需要有一个label属性, 
// 且该label属性的值应该是一个字符串
// 2.输入传入的水下里面的label属性的属性值

// interface 接口实现
interface LabelledValue{
    label:string;   
}
function printLabel2(LabelledObj:LabelledValue){
    console.log(LabelledObj.label);
}
let myObj2 = {size:100,label:"ldqNB"};
printLabel2(myObj2)

// LabelledValue接口就好比一个名字, 
// 用来描述上面例子里的要求
// 它代表了一个有label属性且类型为string的对象

// 类型检查器不回去检查属性的顺序, 
// 只要相应的属性存在并且类型也是对的就可以


// interface 接口实现之可选属性

// 很多框架的API里面都给我们提供了一些可选的属性,
// 用户可以选择是否输入该属性信息,
// 无论输入或是不输入都不会报错
// 可选属性再应用 "option bags" 模式时很常用,
// 即给函数函数传入的参数对象中只有部分属性赋值了

// 带有可选属性的接口与普通的接口定义差不多,
// 只是在可选属性名字定义的后面加一个?符号

interface LabelledValue2{
    label:string;
    name:string;
    // 可选属性
    age?:number;
}
function printLabel3(LabelledObj:LabelledValue2){
    console.log(LabelledObj.label,LabelledObj.name);
}
let myObj3 = {size:10,label:"size 10 Objet", name:'ldq'}
printLabel3(myObj3)


// interface 可选属性的优点
// 可选属性的好处: 
// 一是可以对讯在的属性进行预定义;
// 二是可以捕获引用不存在的属性时的错误;

// 如果没有使用接口的话,那么引用不存在的属性时,是不会报错的
// 当使用了可选属性之后,那么对于这传入的对象里面的属性的引用
// 就会被限制, 如果引用了接口里面未定义的属性时, 就会报错

// 如果没有使用接口的话,那么引用不存在的属性时, 是不会报错的
 


// interface 接口实现之属性检查
// 在可选属性一页中咱们讲过, 
// 当我们给一个对象设置了可选属性, 
// 那么函数内部对于其他的未在接口内定义的参数
// 进行调用就会直接报错
// 不过绕开这些检查也不难

// 1.最简单的方法是使用类型断言
interface SquareConfig{
    color?:string;
    width?:number;
}
function createSquare(config:SquareConfig){
    // 定义默认值
    let newSquare = {color:"white",area:100};
    // color是否传进来
    if(config.color){
        newSquare.color = config.color
    }
    // width是否传进来
    if(config.width){
        newSquare.area = config.width*config.width;clearInterval
    }
    // 返回参数
    return newSquare
}
let mySquare = createSquare({color:"black",width:100} as SquareConfig);

// 2.最佳的方式是在接口里添加一个字符串索引签名
interface SquareConfig2{
    color?:string;
    width?:number;
    // 属性名为字符串的任意值
    [propName:string]:any;
}
function createSquare2(config:SquareConfig){
    // 定义默认值
    let newSquare = {color:"white",area:100};
    // color是否传进来
    if(config.color){
        newSquare.color = config.color
    }
    // width是否传进来
    if(config.width){
        newSquare.area = config.width*config.width;clearInterval
    }
    // 返回参数
    return newSquare
}
let mySquare2 = createSquare2({color:"black",width:100});